using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Runtime.Serialization;

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Pegasus.Runtime.Serialization;
using Pegasus.Runtime.Serialization.Formatters.Xml;

namespace Pegasus.UnitTests.Runtime.Serialization.Formatters.Xml.XmlFormatter2Tests
{
	/// <summary>
	/// This is a test of the deserialization of a hashtable with an unknown type in it.
	/// </summary>
	[TestClass]
	public class XmlFormatter2UnknownTypeTest
	{
		// Local Instance Values
		private TestContext m_testContextInstance;

		/// <summary>
		/// Initializes a new instance of the <see cref="T:XmlFormatter2UnknownTypeTest"/> class.
		/// </summary>
		public XmlFormatter2UnknownTypeTest()
		{
		}

		/// <summary>
		/// Gets or sets the test context which provides information about and 
		/// functionality for the current test run.
		/// </summary>
		/// <value>The test context.</value>
		public TestContext TestContext
		{
			get
			{
				return m_testContextInstance;
			}
			set
			{
				m_testContextInstance = value;
			}
		}

		/// <summary>
		/// Test a hashtable with an unknown type.
		/// </summary>
		[TestMethod]
		public void UnknowTypeTestSubObject()
		{
			Hashtable table = (Hashtable) Deserialize( xmlHashtable1 );

			Assert.IsNotNull( table, "Table was not deserialized correctly" );
			Assert.IsTrue( table.Count == 1, "Table should only have one item it it" );
			Assert.IsNotNull( table[ "TheKey" ], "The key does not exist in the table" );
			Assert.IsTrue( table[ "TheKey" ].GetType() == typeof( object ), "Wrong type was returned should be an object" );
		}

		/// <summary>
		/// Unknows the type test sub object.
		/// </summary>
		[TestMethod]
		public void UnknowTypeTestRootObject()
		{
			object table = Deserialize( xmlHashtable2 );

			Assert.IsNotNull( table, "Table was not deserialized correctly" );
			Assert.IsTrue( table.GetType() == typeof( object ), "Wrong type was returned should be an object" );
		}

		/// <summary>
		/// Deserializes the specified XML.
		/// </summary>
		/// <param name="xml">The XML.</param>
		/// <returns></returns>
		private object Deserialize( string xml )
		{
			// Deserialize the buffer back to an object
			byte[] buffer = Encoding.UTF8.GetBytes( xml );
			using( MemoryStream memStream = new MemoryStream( buffer ) )
			{
				XmlFormatter2 xmlFormatter = new XmlFormatter2( null, new StreamingContext( StreamingContextStates.Persistence ) );
				( (ObjectSerializationBinder) xmlFormatter.Binder ).UnknownTypeReplacement = true;
				return xmlFormatter.Deserialize( memStream );
			}
		}

		/// <summary>
		/// These are a serialed hashtable
		/// </summary>
		private const string xmlHashtable1 = @"
			<XmlFormatter Version='2.0'>
			  <ObjectGraph TypeRef='1' ObjectId='1' ISerializable='true'>
				<LoadFactor TypeRef='2' StringValue='0.72'>
				  <Bytes TypeRef='3'>
					<Bytes_element TypeRef='4'>236</Bytes_element>
					<Bytes_element TypeRef='4'>81</Bytes_element>
					<Bytes_element TypeRef='4'>56</Bytes_element>
					<Bytes_element TypeRef='4'>63</Bytes_element>
				  </Bytes>
				</LoadFactor>
				<Version TypeRef='5'>1</Version>
				<Comparer TypeRef='6'>null</Comparer>
				<HashCodeProvider TypeRef='6'>null</HashCodeProvider>
				<HashSize TypeRef='5'>11</HashSize>
				<Keys TypeRef='7'>
				  <Keys_element TypeRef='8'>TheKey</Keys_element>
				</Keys>
				<Values TypeRef='7'>
				  <Values_element TypeRef='9' ObjectId='2' ISerializable='true'>
					<ticks TypeRef='10'>632897592327913064</ticks>
					<dateData TypeRef='11'>9856269629182688872</dateData>
				  </Values_element>
				</Values>
			  </ObjectGraph>
			  <TypeReferences>
				<Type TypeRef='1'>System.Collections.Hashtable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='2'>System.Single, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='3'>System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='4'>System.Byte, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='5'>System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='6'>System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='7'>System.Object[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='8'>System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='9'>ThisIsTheUnknownTypeForDateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='10'>System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='11'>System.UInt64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
			  </TypeReferences>
			</XmlFormatter>
		";

		private const string xmlHashtable2 = @"
			<XmlFormatter Version='2.0'>
			  <ObjectGraph TypeRef='1' ObjectId='1' ISerializable='true'>
				<LoadFactor TypeRef='2' StringValue='0.72'>
				  <Bytes TypeRef='3'>
					<Bytes_element TypeRef='4'>236</Bytes_element>
					<Bytes_element TypeRef='4'>81</Bytes_element>
					<Bytes_element TypeRef='4'>56</Bytes_element>
					<Bytes_element TypeRef='4'>63</Bytes_element>
				  </Bytes>
				</LoadFactor>
				<Version TypeRef='5'>1</Version>
				<Comparer TypeRef='6'>null</Comparer>
				<HashCodeProvider TypeRef='6'>null</HashCodeProvider>
				<HashSize TypeRef='5'>11</HashSize>
				<Keys TypeRef='7'>
				  <Keys_element TypeRef='8'>TheKey</Keys_element>
				</Keys>
				<Values TypeRef='7'>
				  <Values_element TypeRef='9' ObjectId='2' ISerializable='true'>
					<ticks TypeRef='10'>632897592327913064</ticks>
					<dateData TypeRef='11'>9856269629182688872</dateData>
				  </Values_element>
				</Values>
			  </ObjectGraph>
			  <TypeReferences>
				<Type TypeRef='1'>ThisIsTheUnknownTypeForHashtable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='2'>System.Single, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='3'>System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='4'>System.Byte, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='5'>System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='6'>System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='7'>System.Object[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='8'>System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='9'>System.DateTime, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='10'>System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
				<Type TypeRef='11'>System.UInt64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</Type>
			  </TypeReferences>
			</XmlFormatter>
		";

	}
}
